\#ht\+Scheme A structured and plugin-\/based scheme interpreter implementation.

\subsection*{How to use}

\subsubsection*{Prerequisites}


\begin{DoxyItemize}
\item A modern C++ compiler supporting c++11 feature. (gcc4.\+9.\+2, gcc5.\+1, clang3.\+6 have been tested on Linux)
\item G\+N\+U Make (Make v4.\+0 has been tested on Linux)
\end{DoxyItemize}

\subsubsection*{Make}

Enter the {\ttfamily scheme} directory and run the following commands to generate various targets\+:

\begin{TabularC}{2}
\hline
\rowcolor{lightgray}\PBS\centering {\bf {\bfseries Command} }&\PBS\centering {\bf {\bfseries Function}  }\\\cline{1-2}
\PBS\centering {\ttfamily make}={\ttfamily make all} &\PBS\centering Call everything below except {\ttfamily dep} and {\ttfamily clean} \\\cline{1-2}
\PBS\centering {\ttfamily make cli} &\PBS\centering Generate {\ttfamily cli} (the command-\/line interpreter frontend) \\\cline{1-2}
\PBS\centering {\ttfamily make dep} &\PBS\centering Generate {\ttfamily \hyperlink{dep_8d}{dep.\+d}} which contains the dependencies of files \\\cline{1-2}
\PBS\centering {\ttfamily make clean} &\PBS\centering Remove all files generated by {\ttfamily make} \\\cline{1-2}
\PBS\centering {\ttfamily make preprocessortest}&\PBS\centering Generate {\ttfamily preprocessortest} \\\cline{1-2}
\PBS\centering {\ttfamily make tokenizertest} &\PBS\centering Generate {\ttfamily tokenizertest} \\\cline{1-2}
\PBS\centering {\ttfamily make asttest} &\PBS\centering Generate {\ttfamily asttest} \\\cline{1-2}
\PBS\centering {\ttfamily make parserstest} &\PBS\centering Generate {\ttfamily parserstest} \\\cline{1-2}
\PBS\centering {\ttfamily make biginttest} &\PBS\centering Generate {\ttfamily biginttest} \\\cline{1-2}
\PBS\centering {\ttfamily make rationaltypetest}&\PBS\centering Generate {\ttfamily rationaltypetest} \\\cline{1-2}
\end{TabularC}
You may notice that the compilation is rather slow, therefore you can add {\ttfamily -\/j4} to {\ttfamily make} command in order to parallel the compilation with four threads.

\subsection*{How to develop with ht\+Scheme}

ht\+Scheme has been designed as an extensible architecture of scheme-\/like languages, thus new types of tokens as well as parsers could be easily added into this program.

\subsubsection*{Brief introduction to files}

\paragraph*{\hyperlink{preprocessor_8hpp}{preprocessor.\+hpp}/cpp}

```cpp class \hyperlink{class_scheme_unit}{Scheme\+Unit} \{ public\+: \hyperlink{class_scheme_unit}{Scheme\+Unit(std\+::istream\& scheme\+Stream)}; std\+::vector$<$std\+::string$>$ lines; void preprocess(std\+::istream\& scheme\+Stream); \}; ``{\ttfamily  Accept a}std\+::istream$<$tt$>$as the parameter, then read lines from it untilscheme\+Stream.\+eof(){\ttfamily and remove the comments with the result stored in}lines`.

\paragraph*{\hyperlink{tokenizer_8hpp}{tokenizer.\+hpp}/cpp}

```cpp class \hyperlink{class_tokenizer}{Tokenizer} \{ public\+: \hyperlink{class_tokenizer}{Tokenizer(const std\+::vector$<$std\+::string$>$\& lines)}; void split(const std\+::vector$<$std\+::string$>$\& lines); void parse(const std\+::list$<$std\+::string$>$\& raw\+Tokens); std\+::list$<$std\+::string$>$ raw\+Tokens; std\+::list$<$\+Token$>$ tokens; bool complete; \}; ``{\ttfamily  Accept lines of program, Then}\hyperlink{class_tokenizer_a2a6c04ea8c784f66bebcb6df7073769c}{Tokenizer\+::\+Tokenizer$<$tt$>$}will call\hyperlink{class_tokenizer}{Tokenizer}\+:split{\ttfamily and}Tokernizer\+::parse` in order.

{\ttfamily \hyperlink{class_tokenizer_a8bd8a4eb5df764f6128028daa0e9044b}{Tokenizer\+::split}} splits {\ttfamily lines} into several small string pieces stored in {\ttfamily \hyperlink{class_tokenizer_a89707ad3a758fc9ec58f00d92d5fc622}{Tokenizer\+::raw\+Tokens}}. For example, {\ttfamily (string-\/ith \char`\"{}123 34\char`\"{} 2)} will be split into ``` ( string-\/ith \char`\"{}123 34\char`\"{} 2 ) ```

{\ttfamily \hyperlink{class_tokenizer_ae928efe72c00908a3529747b4cfd01d5}{Tokenizer\+::parse}} convert {\ttfamily \hyperlink{class_tokenizer_a89707ad3a758fc9ec58f00d92d5fc622}{Tokenizer\+::raw\+Tokens}} to {\ttfamily \hyperlink{class_tokenizer_ae547093dbd03b3e70373147e4669d9fa}{Tokenizer\+::tokens}}.

{\ttfamily \hyperlink{struct_token}{Token}} is defined as followed in {\ttfamily \hyperlink{types_2all_8hpp}{types/all.\+hpp}}\+: ```cpp struct \hyperlink{struct_token}{Token} \{ Token\+Type token\+Type; //enum Token\+Type \{Op\+Plus, ...\} Info\+Types info; //typedef boost\+::variant$<$\+Info\+Type1, ...$>$ Info\+Types \}; ```

There is an extra variable {\ttfamily \hyperlink{class_tokenizer_a330a4cce0cbf3ebfbe601d97022d1ed4}{Tokenizer\+::complete}} in this class, which represents whether there is no incomplete brackets or quotaion marks. This could be useful in building command-\/line interpreter. {\ttfamily \hyperlink{class_tokenizer_a330a4cce0cbf3ebfbe601d97022d1ed4}{Tokenizer\+::complete}} can be set by both {\ttfamily \hyperlink{class_tokenizer_a8bd8a4eb5df764f6128028daa0e9044b}{Tokenizer\+::split}} and {\ttfamily \hyperlink{class_tokenizer_ae928efe72c00908a3529747b4cfd01d5}{Tokenizer\+::parse}}.

\paragraph*{\hyperlink{ast_8hpp}{ast.\+hpp}/cpp}

```cpp class \hyperlink{class_a_s_t}{A\+S\+T} \{ public\+: \hyperlink{struct_a_s_t_node}{A\+S\+T\+Node} ast\+Head; void build\+A\+S\+T(const std\+::list$<$\+Token$>$ \&tokens); \hyperlink{class_a_s_t}{A\+S\+T} (const std\+::list$<$\+Token$>$ \&tokens); \hyperlink{class_a_s_t}{A\+S\+T()}; friend std\+::ostream\& operator $<$$<$ (std\+::ostream\& o, const \hyperlink{class_a_s_t}{A\+S\+T}\& ast); \}; ``{\ttfamily  Build an \hyperlink{class_a_s_t}{A\+S\+T} which could be accessed through}\hyperlink{class_a_s_t_a4f9b6d3be381682515e1e51c176b1c21}{A\+S\+T.\+ast\+Head$<$tt$>$}withstd\+::list$<$\+Token$>$`.

Here is the definition of {\ttfamily \hyperlink{struct_a_s_t_node}{A\+S\+T\+Node}}\+: ```cpp struct \hyperlink{struct_a_s_t_node}{A\+S\+T\+Node} \{ Node\+Type type; //enum Node\+Type \{Bracket, Simple\}; \hyperlink{struct_token}{Token} token; A\+S\+T\+Node$\ast$ parent; std\+::list$<$\+A\+S\+T\+Node$\ast$$>$ ch;

A\+S\+T\+Node$\ast$ add(const A\+S\+T\+Node\& node); //ch.push\+\_\+back(new A\+S\+T\+Node(node)) void remove(); //\+Recursively remove all its children then clear ch \}; ```

For example, {\ttfamily (+ 2.\+7 (-\/ 5.\+6 2.\+1) 3)} will be converted to the following \hyperlink{class_a_s_t}{A\+S\+T}\+: ``` Type\+:0 \hyperlink{struct_token_a4c338f6ca199f4a8575e877d36d03a06}{Token.\+info}\+:0 Token\+Type\+:0 //ast\+Head +-\/---Type\+:Bracket \hyperlink{struct_token_a4c338f6ca199f4a8575e877d36d03a06}{Token.\+info}\+:0 Token\+Type\+:0 +---Type\+:Simple \hyperlink{struct_token_a4c338f6ca199f4a8575e877d36d03a06}{Token.\+info}\+:0 Token\+Type\+:Op\+Plus $\vert$---Type\+:Simple \hyperlink{struct_token_a4c338f6ca199f4a8575e877d36d03a06}{Token.\+info}\+:2.\+7 Token\+Type\+:Float $\vert$---Type\+:Bracket \hyperlink{struct_token_a4c338f6ca199f4a8575e877d36d03a06}{Token.\+info}\+:0 Token\+Type\+:0 $\vert$ +---Type\+:Simple \hyperlink{struct_token_a4c338f6ca199f4a8575e877d36d03a06}{Token.\+info}\+:0 Token\+Type\+:Op\+Minus $\vert$ $\vert$---Type\+:Simple \hyperlink{struct_token_a4c338f6ca199f4a8575e877d36d03a06}{Token.\+info}\+:5.\+6 Token\+Type\+:Float $\vert$ $\vert$---Type\+:Simple \hyperlink{struct_token_a4c338f6ca199f4a8575e877d36d03a06}{Token.\+info}\+:2.\+1 Token\+Type\+:Float $\vert$---Type\+:Simple \hyperlink{struct_token_a4c338f6ca199f4a8575e877d36d03a06}{Token.\+info}\+:3 Token\+Type\+:Float ```

\paragraph*{\hyperlink{parsers_8hpp}{parsers.\+hpp}}

The main part of {\ttfamily \hyperlink{parsers_8hpp}{parsers.\+hpp}} is in {\ttfamily \hyperlink{parsers_2all_8hpp}{parsers/all.\+hpp}}

```cpp class \hyperlink{class_parsers_helper}{Parsers\+Helper} \{ \hyperlink{class_parsers_helper}{Parsers\+Helper()}; void parse(\+A\+S\+T\+Node\& astnode); \}; ``{\ttfamily  Provide a reference of}\hyperlink{struct_a_s_t_node}{A\+S\+T\+Node}{\ttfamily to an instance of}\hyperlink{class_parsers_helper_a21ce6213ee29e0459dd655c6803db00b}{Parsers\+Helper\+::parse$<$tt$>$}, then\hyperlink{class_parsers_helper}{Parsers\+Helper}{\ttfamily will call according}xxx\+A\+S\+T\+Parser\+::parse(\+A\+S\+T\+Node\& parent, Parsers\+Helper\& helper){\ttfamily to recursively calculate the result of a subtree of \hyperlink{class_a_s_t}{A\+S\+T} with its root as}astnode{\ttfamily . After}\hyperlink{class_parsers_helper_a21ce6213ee29e0459dd655c6803db00b}{Parsers\+Helper\+::parse$<$tt$>$},astnode.\+type$<$tt$>$will becomeSimple{\ttfamily . If}astnode{\ttfamily is already a}Simple` node, nothing will be done.

The parsed version of the above \hyperlink{class_a_s_t}{A\+S\+T} is (by calling {\ttfamily parse( $\ast$$\ast$ast.head\+Node.\+ch.\+begin() )}\+: ``` Type\+:1 \hyperlink{struct_token_a4c338f6ca199f4a8575e877d36d03a06}{Token.\+info}\+:0 Token\+Type\+:0 //head\+Node +-\/---Type\+:Simple \hyperlink{struct_token_a4c338f6ca199f4a8575e877d36d03a06}{Token.\+info}\+:9.\+2 Token\+Type\+:Float ```

{\bfseries Warning} --D\+O N\+O\+T-- directly call {\ttfamily helper.\+parse($\ast$ch\mbox{[}xx\mbox{]})} in {\ttfamily xxx\+A\+S\+T\+Parser\+::parse(\+A\+S\+T\+Node\& parent, Parsers\+Helper\& helper)} ! Instead, you should copy construct a new {\ttfamily \hyperlink{class_parsers_helper}{Parsers\+Helper}} to parse its children.

\subsubsection*{Add your own \hyperlink{struct_token}{Token} Parser}

In this section, we will try to add a new {\ttfamily Rational} type of token.

\paragraph*{Step1\+: Register the Rational Type}

Open {\ttfamily \hyperlink{types_2arch_8hpp}{types/arch.\+hpp}}, add {\ttfamily Rational} to {\ttfamily enum Token\+Type\{ ... , Rational \}}

\paragraph*{Step2\+: Register the Rational Parser}


\begin{DoxyItemize}
\item Open {\ttfamily \hyperlink{types_2all_8hpp}{types/all.\+hpp}}, add {\ttfamily Rational\+Parser} to {\ttfamily \#define P\+A\+R\+S\+E\+R\+S\+\_\+\+T\+U\+P\+L\+E (..., Rational\+Parser)}
\item {\ttfamily \#include \char`\"{}rational.\+hpp\char`\"{}}
\end{DoxyItemize}

\paragraph*{Step3\+: Write the Header}


\begin{DoxyItemize}
\item Create {\ttfamily \hyperlink{rational_8hpp}{types/rational.\+hpp}}, then include your declaration of your {\ttfamily \hyperlink{class_rational_type}{Rational\+Type}} and {\ttfamily \char`\"{}arch.\+hpp\char`\"{}}
\item Use the macro in {\ttfamily arch.\+hpp} to generate the declaration of your {\ttfamily Rational\+Parser} \+: ``` \hyperlink{types_2arch_8hpp_a669f5b829a7373f20602e4c063e01d99}{P\+A\+R\+S\+E\+R\+\_\+\+D\+E\+C\+L\+A\+R\+A\+T\+I\+O\+N(\+Rational\+Parser, Rational, Rational\+Type)} ```
\end{DoxyItemize}

\paragraph*{Step4\+: Implement the Parser}


\begin{DoxyItemize}
\item Create {\ttfamily \hyperlink{rational_8cpp}{types/rational.\+cpp}}, then {\ttfamily \#include \char`\"{}rational.\+hpp\char`\"{}} and implement your {\ttfamily \hyperlink{class_rational_type}{Rational\+Type}} in it.
\item Implement {\ttfamily bool Rational\+Parser\+::judge(const std\+::string\& token)} which returns whether a token is a rational token and {\ttfamily Rational\+Parser\+::\+Info\+Type Rational\+Parser\+::get(const std\+::string\& token)} which converts the token to {\ttfamily Rational\+Parser\+::\+Info\+Type}(aka {\ttfamily \hyperlink{class_rational_type}{Rational\+Type}})
\item {\ttfamily const Token\+Type Rational\+Parser\+::type = Rational;} 
\end{DoxyItemize}